package com.mrd.permissions;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.lang.time.DateUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mrd.gtimpframe.entity.SysLog;
import com.mrd.gtimpframe.repository.SysLogMapper;
import com.mrd.redis.JedisClientClusterImpl;

@Service
public class LogBathSaveTask implements InitializingBean {
  @Autowired
  private JedisClientClusterImpl redisClusterClient;
  private List<SysLog> list = Collections.synchronizedList(new ArrayList<SysLog>());
  @Autowired
  private SysLogMapper sysLogMapper;
  @Autowired
  SqlSessionTemplate sqlSessionTemplate;
  private final Logger logger = LoggerFactory.getLogger(LogBathSaveTask.class);

  @Override
  public void afterPropertiesSet() throws Exception {
    new Thread(new BathTaskConsumer()).start();
  }

  /**
   * 批量入队，保存方法
   * 
   * @author han
   */
  public class BathTaskConsumer implements Runnable {

    @Override
    public void run() {
      new Timer().schedule(new TimeSaveTask(), 0, 60 * 1000 * 5);

      while (true) {
        try {
          SysLog log = redisClusterClient.rightPop("sysLog", SysLog.class);
          if (log != null) {
            // logger.info("日志出队：" + log.getExecMethod());
            list.add(log);
            if (list.size() == 25) {
              // 批量保存
              bathSave(list);
              list.clear();
            }
          }
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        } catch (Exception ex) {
          logger.error("日志保存出错：" + ex.getMessage());
        }
      }
    }

    public void bathSave(List<SysLog> list) {
      SqlSession session = null;
      try {
        session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);// 获取批量方式的sqlsession

        for (int i = 0, size = list.size(); i < size; i++) {
          session.insert("com.mrd.gtimpframe.repository.SysLogMapper.insert", list.get(i));
        }
        session.commit();
        session.clearCache();
      } catch (Exception ex) {
        session.rollback();
      } finally {
        session.close();
      }
    }

    /**
     * 定时保存任务
     * 
     * @see 当队列不满30个的时候，如果队列的最新的数据有两分钟不处理，自动入库
     * @author han
     *
     */
    public class TimeSaveTask extends TimerTask {

      @Override
      public void run() {
        if (list.size() > 0) {
          logger.info("定时入库执行");
          SysLog lastLog = list.get(list.size() - 1);
          Date dtmTime = DateUtils.truncate(lastLog.getCtime(), Calendar.MINUTE);
          Date ntime = DateUtils.truncate(new Date(), Calendar.MINUTE);
          long from = dtmTime.getTime();
          long to = ntime.getTime();
          int minutes = (int) ((to - from) / (1000 * 60));
          if (minutes >= 2) {
            bathSave(list);
            list.clear();
          }
        }
      }

    }
  }

}


